// classes example
#include <iostream>
#include <stdio.h>      /* printf, scanf, puts, NULL */
#include <stdlib.h>     /* srand, rand */
#include <time.h>       /* time */
#include <math.h>		/* exp */
#include "FCLayer.h" 
// #include "FL_model_weights.h"
#include <cstring>
//#include "Particle.h"
//#include <Arduino.h>
using namespace std;

//TODO: PUT THIS SOMEWHERE srand (time(NULL));

/*
ActivationLayer::ActivationLayer(double **inp){
	double **input_data = inp;
}

ActivationLayer::forward(double **input_float, double **output){
	input_size = sizeof(*input_data[0])
	for(int i = 0; i < input_size; ++i){
		delete [] input_data[i];
	}

	input_data = input_float;

	for(int b = 0; b < batch_size; b++){
		for(int j = 0; j < output_size; j++){
			output[b][j] = tanh(output[b][j]);
		}
	}
}

ActivationLayer::backward(double **output_error, double **input_error, double double learning_rate){
	//the length of input_error is the output_size of the previous FC layer in the stack
	for(int b = 0; b < batch_size; b++){
		double err = 0.0;
		for(int j = 0; j < sizeof(*input_error[0]); j++){
			input_error[b][j] = tanh(input_data);
		}
	}
}

ActivationLayer::~ActivationLayer() { 
	input_size = sizeof(*input_data[0])
	for(int i = 0; i < input_size; ++i){
		delete [] input_data[i];
	}
}
*/

const double initial_model_bias[] = {0.00928613, -0.01084625};
const double initial_model_weights[] = {
  -0.04986883,  0.05147216,  0.06779706,  0.04711119, -0.04426132,
       -0.00808981, -0.01073406, -0.05141388,  0.05659899, -0.00556131,
        0.03012036, -0.03470106,  0.03839   , -0.08626562, -0.05883501,
        0.06057981, -0.01847088, -0.05610036, -0.03804394, -0.05494943,
       -0.03376978,  0.08608717,  0.01615667,  0.02342767,  0.04767524,
       -0.04941383, -0.02384711,  0.04341529, -0.02033149, -0.06593148,
       -0.04635327, -0.01481599, -0.06649264,  0.01314451,  0.06444126,
       -0.03957188,  0.03744897,  0.05697426,  0.05657213,  0.00027597,
        0.0443212 , -0.02874512, -0.01796832,  0.06386174, -0.06618255,
       -0.00272596,  0.02670988,  0.01128878,  0.03347297,  0.02936709,
       -0.06393223, -0.05380874,  0.05002271, -0.01337717,  0.01597454,
       -0.04923081,  0.0559905 , -0.03472501,  0.04173714, -0.03898819,
        0.06168495, -0.02970989,  0.01201072, -0.01931893,  0.01503393,
        0.00255075, -0.03348528,  0.04689924, -0.00507433,  0.03096186,
       -0.03947238, -0.04490383, -0.04260084,  0.00360482,  0.01413764,
        0.01070482, -0.06445587, -0.02271118,  0.01158464, -0.05073335,
        0.06012097,  0.03472614,  0.04067348,  0.02940062,  0.04410675,
       -0.00617929,  0.01855445, -0.04642124, -0.06735183,  0.05474162,
        0.00233633, -0.06569151, -0.01529454,  0.04206371,  0.05538685,
       -0.06844267,  0.05353102, -0.02960159, -0.0560516 ,  0.00706074,
        0.02596323, -0.0209138 , -0.03238627, -0.04364531,  0.04565633,
       -0.01666962,  0.03973407,  0.00618519, -0.05226628, -0.06055015,
        0.04006798, -0.051706  , -0.03206879,  0.05438478, -0.02826099,
        0.05997315,  0.03790734, -0.02209917,  0.06891475, -0.09334138,
       -0.06438693, -0.00246445,  0.0178271 , -0.00501667,  0.02673081,
       -0.00124886,  0.02639395,  0.00460046,  0.00495609,  0.04968096,
       -0.06104689,  0.04196995,  0.02809841, -0.04941421, -0.02798566,
        0.00081764, -0.03428812, -0.0269298 , -0.01611065,  0.03633194,
       -0.01415959, -0.01198585,  0.02534599,  0.05778414, -0.06242159,
       -0.01888462,  0.02328136, -0.02981369, -0.05137242,  0.05463824,
       -0.05142897,  0.06359849,  0.00536932,  0.03368448,  0.10815594,
       -0.07851613, -0.04731192,  0.06353287,  0.10306776,  0.00364497,
       -0.04960258, -0.00196934, -0.04368044, -0.06364923, -0.03379036,
        0.00882445, -0.00077784,  0.01805788, -0.0436746 , -0.05155381,
       -0.03816003, -0.02252579,  0.04685578,  0.04487075,  0.02570475,
        0.01337013, -0.0091351 , -0.02392822,  0.03296599,  0.02653806,
       -0.00513988,  0.05125958,  0.02013943, -0.04817565, -0.02753871,
       -0.0410315 ,  0.04282894, -0.04943141, -0.0382863 ,  0.02458231,
        0.04200376, -0.04830738,  0.0601626 , -0.00898704, -0.06704461,
        0.00023379,  0.06274279,  0.04558692, -0.01623473,  0.04600406,
       -0.00280977,  0.01726177,  0.06285498, -0.00749676, -0.0100912 ,
        0.00499561, -0.04747301, -0.04909431, -0.06244412, -0.03186803,
       -0.02328847, -0.00632372,  0.02075882, -0.02656947,  0.02032968,
       -0.01378108, -0.02171962,  0.08472694, -0.05834733,  0.03664124,
       -0.02214718,  0.05884986, -0.04103148,  0.01190325,  0.05222489,
       -0.04137358,  0.03132067, -0.00269074,  0.05827191,  0.02015483,
       -0.04894547,  0.02462604,  0.04260305, -0.02251578, -0.01642913,
       -0.00963962, -0.04621717,  0.03291727,  0.00237798, -0.01111561,
        0.03221402, -0.0208841 ,  0.00355671, -0.02395363,  0.03065113,
       -0.04697239,  0.06675602, -0.03426993, -0.0234666 ,  0.05181156,
       -0.06589997,  0.05638531, -0.04193888,  0.02972519,  0.01766346,
        0.04094022, -0.01608195, -0.04458919,  0.04967248,  0.02002505,
       -0.01481748, -0.04403269, -0.00588238,  0.05659971,  0.01145547,
        0.04558631, -0.05247139, -0.04383749,  0.03386389,  0.06274936,
       -0.03031638,  0.0321687 ,  0.03203706, -0.01655196, -0.04069622,
       -0.01908031, -0.03713522, -0.0122619 ,  0.06110764,  0.06707244,
       -0.03102955,  0.04375848,  0.02291304, -0.00823033,  0.05551676,
        0.0681195 ,  0.07115228, -0.01925835, -0.03154208, -0.0652104 ,
        0.00749914, -0.02473656,  0.03486815, -0.08225901, -0.05838262,
       -0.01459291, -0.00709413,  0.0566624 ,  0.05821289,  0.02887758,
       -0.02874063,  0.04160416,  0.01590604,  0.00391822,  0.02825015,
        0.03582568,  0.0323678 ,  0.00307163,  0.007571  , -0.03739319,
       -0.00846189, -0.03846331,  0.05229042, -0.0078    ,  0.0625329 ,
       -0.05274488, -0.05539851,  0.0574416 ,  0.00758747,  0.02608308,
        0.02165091, -0.04215403,  0.04086292, -0.06133611,  0.05703198,
       -0.03840946,  0.00619143,  0.0148174 ,  0.00663488,  0.07964408,
        0.04127401,  0.04382094, -0.06283553,  0.06521175, -0.01186521,
       -0.06383476,  0.00559762,  0.00626112,  0.01497961, -0.01465149,
        0.03659768,  0.06519307,  0.0518705 ,  0.05911824,  0.04285912,
       -0.02614333,  0.024383  , -0.05284642,  0.03330771, -0.00929528,
       -0.04384527,  0.04258467,  0.03887638,  0.02021926,  0.01851348,
        0.0588222 ,  0.01926945, -0.03648695,  0.04839437,  0.01798506,
       -0.04532311,  0.01518791, -0.00691865,  0.06627014,  0.04890645,
       -0.0325288 , -0.03542892,  0.00550156, -0.03272511, -0.01898336,
       -0.05901914,  0.11902577, -0.02490444, -0.06330227, -0.01562487,
        0.02862391, -0.05327774,  0.05829268, -0.06514993, -0.03578205,
        0.04645992, -0.02500404,  0.02737958, -0.02387937, -0.00569954,
       -0.014872  ,  0.04406305,  0.04700563, -0.09713408,  0.09217192,
       -0.03742706, -0.0424301 ,  0.05612912, -0.00281021,  0.08434386,
       -0.07737077, -0.00776984, -0.08388144, -0.01842652,  0.04042467,
        0.05072198, -0.04626399,  0.04005648, -0.00925637,  0.01877343,
       -0.02112312, -0.06150386,  0.00099474, -0.00758383,  0.06499062,
       -0.03380001,  0.0663208 , -0.06489117,  0.03716885, -0.02996751,
        0.04104346, -0.04899608, -0.05644024,  0.03149898, -0.05156257,
        0.05347704,  0.03980342, -0.04639796, -0.02722636, -0.04265547,
       -0.00811785,  0.02971107,  0.02983294,  0.03130453, -0.00419168,
       -0.02031822,  0.00286633,  0.05250997, -0.00259594, -0.03877416,
       -0.07355434,  0.01132608,  0.06753467,  0.00351719,  0.06012332,
       -0.04928384,  0.04634202,  0.02177063, -0.02388674, -0.02726197,
        0.03813621,  0.03837039,  0.02758718,  0.0670227 ,  0.06042802,
        0.06645659,  0.01142233, -0.00198312,  0.02335508,  0.06184483,
        0.01260431, -0.05679801,  0.00276751, -0.00082096,  0.00724509,
        0.0275539 ,  0.01121085,  0.00472076,  0.02850279, -0.01397151,
        0.0752602 , -0.00915412,  0.04398358, -0.0235371 ,  0.04728065,
        0.000323  , -0.04815008, -0.04400115, -0.01831324, -0.00661721,
        0.04579612, -0.05803587,  0.06911585,  0.06586176, -0.07465558,
        0.04600189,  0.022461  ,  0.06819102, -0.0407792 , -0.06007536,
       -0.05490214,  0.06097953,  0.02988418, -0.03909811,  0.00914587,
       -0.04155681,  0.04898534, -0.00735962,  0.0233679 ,  0.06328844,
       -0.03143546,  0.05736325, -0.03283874, -0.05203191,  0.01180522,
       -0.00491153,  0.0251397 ,  0.00188234, -0.0056041 ,  0.0106394 ,
       -0.06655177, -0.04110413, -0.01331838,  0.00684707, -0.06284221,
       -0.02135598,  0.03368284, -0.0495897 , -0.02313039,  0.14105704,
       -0.14541271, -0.09993366,  0.09831917,  0.0255979 , -0.02713414,
       -0.05420853,  0.06262331,  0.03008276, -0.03756777,  0.01569442,
       -0.0240251 ,  0.0265922 ,  0.0325783 , -0.0529187 , -0.03751227,
       -0.03889522, -0.01324275, -0.0032736 , -0.0310485 ,  0.00233753,
        0.06362607, -0.00977268,  0.00852914,  0.0581774 , -0.02730154,
       -0.06651135,  0.01339391, -0.00620122, -0.04976916,  0.06838899,
        0.00452419, -0.01958459, -0.05714595,  0.01718999,  0.06718368,
       -0.01247382, -0.03955964, -0.00604017,  0.05938308,  0.06312367,
       -0.0525844 ,  0.03346466,  0.04005408, -0.04801833, -0.04020742,
        0.00190391,  0.04626376,  0.04794168, -0.06230603,  0.08129318,
       -0.11885372,  0.01518134,  0.0606775 , -0.05371692, -0.0432546 ,
       -0.0117309 , -0.05740631,  0.01569967, -0.05218379, -0.01235998,
       -0.05782488, -0.02839773, -0.02692272, -0.05387751,  0.05685003,
       -0.04967549, -0.05413853, -0.00550079,  0.05006272, -0.08329152,
        0.01016719,  0.04228862, -0.0375314 ,  0.0427388 , -0.00495645,
        0.00249758,  0.03807524,  0.01326782, -0.03653573,  0.06734706,
       -0.06789851,  0.04096781, -0.00920784, -0.05790277, -0.05810594,
       -0.01082786,  0.01778961,  0.01029776,  0.05285995, -0.06313071,
        0.04930902,  0.00592698,  0.07391646, -0.0048902 ,  0.06637292,
       -0.00608631, -0.00021724,  0.01771292,  0.04213746,  0.01389056,
       -0.02744349,  0.03291008, -0.04519217, -0.02787772, -0.02560733,
        0.06237136,  0.02767685, -0.03753496,  0.01486455, -0.04420446,
        0.05949682,  0.00701635, -0.06594213, -0.04817586, -0.0421104 ,
        0.040928  ,  0.05045984,  0.03211144, -0.01242441, -0.05476344,
        0.00363029,  0.04068471, -0.01275429,  0.03834535, -0.06863745,
       -0.06621079,  0.02736422,  0.05123235,  0.00336451,  0.03410865,
       -0.01101965,  0.02797758,  0.03099268,  0.00874935, -0.09062176,
       -0.05045577,  0.00674525,  0.00613857, -0.06612045,  0.04282364,
        0.00957711,  0.01270785,  0.00875174, -0.01213996,  0.02031978,
       -0.01299324,  0.03689544,  0.10033362, -0.05260235,  0.03559503,
       -0.02167666, -0.13927773,  0.02906977,  0.05206958, -0.01877782,
       -0.02179723,  0.05768301,  0.00343911, -0.04151925,  0.05353428,
       -0.01764055,  0.02266793, -0.06583817,  0.02556075, -0.10766762,
       -0.05062919,  0.04032819,  0.01217977, -0.02598631,  0.02380826,
        0.0177389 , -0.01652595, -0.04683262, -0.04141673, -0.00972991,
       -0.05831567, -0.02219007, -0.03492446,  0.06398657,  0.03329459,
       -0.02694833,  0.00063051,  0.04616494, -0.01322604,  0.06433789,
       -0.00508566,  0.03494992, -0.02800843,  0.05701336,  0.10291377,
       -0.01618041,  0.06134265,  0.00988659, -0.0183774 ,  0.07492772,
        0.05563013,  0.05961767, -0.06187775, -0.03632844, -0.01126505,
        0.00094396, -0.04223967, -0.06882508,  0.06434742, -0.02424874,
       -0.01096154, -0.06106392, -0.0609151 ,  0.03642609,  0.04309765,
       -0.06278715,  0.03631101,  0.03482132,  0.01289454,  0.06187368,
       -0.05682466,  0.03962876,  0.05499651,  0.04219571, -0.00388628,
       -0.05262237, -0.00609811, -0.06324966, -0.0107387 ,  0.01442757,
        0.06245889, -0.02265857,  0.02024399, -0.04764255,  0.04871157,
        0.02693198, -0.02886936,  0.03718804,  0.02517936,  0.03558664,
        0.0644031 , -0.02919663, -0.05950025,  0.05110598,  0.07130128,
       -0.03111605, -0.01906604,  0.00495167,  0.08268971, -0.06036561,
        0.00554271, -0.08000334,  0.0533299 ,  0.03031353,  0.03654531,
       -0.03849236,  0.03063541, -0.03810867,  0.03234813, -0.05590491,
        0.05782714, -0.00599344, -0.04393106, -0.04878129, -0.03991513,
        0.04885834, -0.02307287,  0.03629626, -0.05725558, -0.06876009,
       -0.06461642,  0.0191187 ,  0.01297383,  0.0262565 ,  0.01418297,
        0.03808422,  0.0271949 ,  0.05016553,  0.00175256,  0.03665943,
        0.05987562, -0.02379376,  0.02648809, -0.05301794, -0.03161386,
       -0.03904074, -0.02582399,  0.05838474, -0.06320224,  0.00037957,
        0.03034044, -0.00068369, -0.065566  ,  0.06458597,  0.05510646,
       -0.03404083,  0.04682944,  0.06430103,  0.067668  ,  0.02194601,
        0.01273898,  0.05598538, -0.03710455,  0.0044319 , -0.0202256 ,
        0.02646333,  0.04084804,  0.02454249,  0.07287139, -0.07523429,
       -0.01928756, -0.0063081 ,  0.06872251,  0.00519456,  0.02014771,
       -0.03472866, -0.06221005,  0.01903557, -0.01665994, -0.01515154,
        0.01280382, -0.02938079, -0.00730397, -0.03401773, -0.01174972,
        0.02733961, -0.02054671, -0.0306045 ,  0.06026255,  0.04400207,
        0.03422117, -0.06288271,  0.03228074, -0.05808453,  0.03391718,
        0.00787976, -0.00973229,  0.02972766, -0.03554901,  0.02476132,
       -0.09306902,  0.16411339, -0.0252324 ,  0.04719837, -0.00257106,
        0.00850551, -0.05859038, -0.00343101, -0.04315638,  0.05822231,
        0.01749963, -0.05849799, -0.07618199,  0.01033679,  0.0187277 ,
       -0.0211855 , -0.0286006 , -0.03436195, -0.0209845 ,  0.02734033,
        0.06807754, -0.03277271,  0.01941858, -0.0265089 ,  0.00425502,
        0.04472636,  0.04924395, -0.02899726,  0.02935156, -0.00799865,
        0.04409884,  0.01479255, -0.06823739, -0.01152181,  0.00881075,
       -0.01893997,  0.00201051,  0.02627011,  0.03007634,  0.06166803,
        0.06041211,  0.04297597, -0.01995902, -0.00609376, -0.00630004,
        0.03149701,  0.02371705,  0.02937618, -0.00249373,  0.03960955,
       -0.0156478 ,  0.00826131,  0.04893415,  0.00319006,  0.02452863,
       -0.04856218,  0.0369024 ,  0.00393927,  0.00786753,  0.0040465 ,
        0.06699312, -0.06035319,  0.03348283, -0.03963458, -0.05612253,
       -0.0599854 , -0.00878131, -0.0212218 , -0.00457856, -0.04324048,
        0.03531986, -0.05023393,  0.06616075,  0.04460708, -0.02818419,
       -0.0247028 ,  0.02694707, -0.06184774, -0.01216908,  0.02806778,
        0.01276175, -0.01810116,  0.03504111,  0.05449504, -0.01748259,
        0.00247794,  0.02542433, -0.02664481,  0.02615543, -0.05918081,
       -0.00221207,  0.02272179, -0.06578194, -0.00346585,  0.03527688,
       -0.00691065, -0.0508377 ,  0.08978587,  0.13360165, -0.15158586,
        0.0433656 ,  0.02728339,  0.06383169, -0.04535145,  0.02853326,
        0.06022611,  0.06156285, -0.04108287, -0.13098407,  0.14182968,
        0.0514304 , -0.02140733, -0.03001766,  0.03967052,  0.0033683 ,
       -0.01607488,  0.02480412, -0.00898199,  0.04452249, -0.08569242,
        0.04587787,  0.03720341, -0.03497298,  0.06687345, -0.06591109,
        0.05000704, -0.00237581, -0.01090469, -0.02902387, -0.05457027,
        0.03493633, -0.03694495,  0.06613066,  0.04053158,  0.06197319,
       -0.02148426,  0.05917997, -0.03991104, -0.01190234,  0.0558523 ,
        0.00482307, -0.00203693, -0.04448053,  0.06253775, -0.05216776,
       -0.00176363, -0.05194866,  0.02279722, -0.03057496, -0.01596991,
        0.1081441 , -0.09234061, -0.08765355,  0.00031925, -0.02477618,
        0.0293635 , -0.0246399 ,  0.05036936,  0.02387886, -0.06202587,
       -0.0216084 , -0.02960877, -0.03442111, -0.044351  ,  0.05706355,
       -0.02907251, -0.04269931,  0.04074436,  0.04453014, -0.03296679,
       -0.03759745,  0.03218165, -0.01128062,  0.01220433, -0.01121383,
        0.05715936,  0.00846848, -0.05261331,  0.0078166 , -0.01300646,
        0.01273762,  0.0160613 ,  0.04033395,  0.01450646, -0.04407576,
        0.02013518, -0.02458063, -0.03933021,  0.0580701 ,  0.0235999 ,
        0.01446185, -0.07021026, -0.05774702,  0.02367598, -0.06125634,
       -0.01949079,  0.0397991 ,  0.06840856, -0.00637908, -0.02626793,
        0.09908788, -0.05012249, -0.06510761,  0.02320304, -0.03653684,
       -0.06917541, -0.04654066,  0.0011821 , -0.02955791, -0.03841074,
        0.0020004 ,  0.02564169, -0.03841071,  0.01689169, -0.03457003,
        0.03062649,  0.06994179, -0.01975791, -0.02297208, -0.00479423,
        0.02741211,  0.02141522,  0.00198927,  0.04308906,  0.01657081,
        0.01697552, -0.05422651,  0.02273714, -0.06514774,  0.05113615,
        0.02999653, -0.00377267, -0.00066505,  0.02286881,  0.02957906,
       -0.0445116 ,  0.02888911, -0.02128288,  0.06322014,  0.04419039,
        0.0018867 , -0.011276  ,  0.00539003, -0.03262925, -0.0054807 ,
        0.0563786 , -0.05114885,  0.02114552, -0.05785131, -0.00665591,
        0.06948552, -0.04004502, -0.04120921, -0.03575188, -0.02710559,
       -0.04588011, -0.01918895,  0.004222  , -0.01223358, -0.01107455,
       -0.0261139 ,  0.01669525,  0.0450362 ,  0.05530252,  0.03402747,
       -0.06615375, -0.0584234 ,  0.05463162,  0.01220605, -0.05697535,
        0.00243825,  0.05235574,  0.06620866, -0.0146198 , -0.06305692,
        0.02963435, -0.03978744, -0.04635312,  0.03210439, -0.02337122,
        0.08787385,  0.01074616,  0.06325503, -0.05816434, -0.01011831,
        0.05865861, -0.03567105, -0.00673135, -0.05556689,  0.02429135,
       -0.05719045, -0.02970347, -0.0384802 , -0.00976372,  0.01062896,
        0.06547816, -0.03945315,  0.02836552,  0.01738762,  0.0494704 ,
        0.03183694, -0.01478442, -0.00165997, -0.03604353, -0.03157174,
        0.01780997, -0.02940754, -0.00698802,  0.05651606,  0.00649405,
        0.05657458,  0.02430348,  0.0467354 ,  0.04047847,  0.00159691,
       -0.01638936,  0.04370815,  0.04906692, -0.01004469,  0.04030346,
        0.00957103,  0.02430784, -0.01958551,  0.00262593, -0.03420136,
       -0.03652073,  0.04461606,  0.05472482, -0.05729968, -0.05348232,
       -0.04835982, -0.0420017 , -0.05847165,  0.07224914,  0.05712642,
        0.01340189, -0.03146996,  0.01503159,  0.04789844, -0.06738538,
        0.06779749,  0.04436806, -0.0208877 , -0.05489728, -0.05398356,
       -0.05921177,  0.01207205, -0.00599197,  0.00311769,  0.02581261,
       -0.03538422, -0.05865448, -0.02677247, -0.01766012,  0.063615  ,
       -0.06728299, -0.04329587, -0.06104322,  0.01101007, -0.04417879,
        0.05021101,  0.06183705,  0.05828772, -0.03557809,  0.01082018,
       -0.03971267,  0.05364642, -0.0338602 ,  0.06579822, -0.05080821,
        0.0092261 ,  0.02194817,  0.0612682 ,  0.06611536,  0.00714105,
       -0.03759037,  0.06858637, -0.01018946,  0.0275396 , -0.03621583,
       -0.04716884, -0.02269784,  0.01291246,  0.0202621 ,  0.01967349,
       -0.04910871, -0.03493998, -0.0454453 ,  0.00807681,  0.03509654,
        0.01252364, -0.02612831,  0.04392291, -0.04905645, -0.01643094,
       -0.06544188, -0.07246992,  0.01601614, -0.05868346, -0.05340097,
        0.05763379, -0.06773402,  0.05107352,  0.01046493,  0.03287298,
       -0.00414705,  0.00359053, -0.0325595 , -0.01470922,  0.07218453,
       -0.04583156,  0.03562868,  0.03740682, -0.06494787, -0.00827079,
       -0.00606636, -0.02877736,  0.06224332, -0.06207858, -0.06355225,
        0.0374181 , -0.09202727,  0.04447626, -0.01371025, -0.05718485,
        0.04354205, -0.01552411,  0.01363068, -0.01535428,  0.07320999,
        0.00163129,  0.01094238,  0.02029449, -0.02244845,  0.04975579,
       -0.0084274 , -0.04501924, -0.04668131, -0.02131925, -0.01450618,
       -0.05738336,  0.03981732, -0.0510693 , -0.00141075,  0.04819461,
       -0.04602249,  0.03617683,  0.05699704, -0.05438528, -0.05898988,
       -0.02950299, -0.01020762,  0.02639509, -0.05590928,  0.01872724,
        0.04372935, -0.05177999,  0.02043038, -0.01312306,  0.00878694,
        0.01026168, -0.02573187, -0.03070647, -0.04973008,  0.12812307,
       -0.05889556,  0.04938043,  0.0320729 ,  0.05945608,  0.00460093,
       -0.04676374, -0.01943221, -0.00435062, -0.03509559, -0.04511632,
        0.06075845,  0.06862984, -0.03098488,  0.03133912, -0.01519907,
       -0.02374493, -0.02611005, -0.03740479,  0.06611076, -0.04584803,
       -0.05447748,  0.00699806, -0.05044371, -0.01434573, -0.04682435,
        0.02471794, -0.03188854,  0.02313998,  0.05376269,  0.01079839,
       -0.02171007, -0.04986876, -0.01854862, -0.04823213, -0.05063184,
       -0.03320568,  0.04027656, -0.04325845, -0.06471736, -0.02809649,
       -0.02580778,  0.02087202, -0.0204653 , -0.01164313,  0.0046186 ,
        0.0368775 , -0.02326602,  0.04833511,  0.00239751, -0.06621278,
        0.06194474,  0.05639874, -0.06759892,  0.04940527, -0.04670576,
       -0.04005842,  0.03650521, -0.06549253,  0.04653824,  0.06169763,
       -0.0365978 ,  0.06891026,  0.02852459, -0.03966541, -0.03883598,
        0.02076291,  0.02370548, -0.04781282,  0.06119591,  0.01762301,
       -0.09996177,  0.06819325,  0.04981492, -0.03424763,  0.0365211 ,
       -0.05999442, -0.03827229,  0.02067816, -0.02773934, -0.06595086,
       -0.00988098,  0.00972274,  0.04754295,  0.00249878, -0.05478235,
       -0.01648224, -0.03206048,  0.03137148, -0.05921698,  0.06660374,
       -0.04188423, -0.00532982,  0.04886613, -0.00279573,  0.04941839,
        0.10855461, -0.00458986,  0.04342438,  0.0635015 ,  0.03100703,
       -0.05705556,  0.00826816,  0.02207248,  0.10378865, -0.05556004,
        0.02775606, -0.01848496, -0.04366614,  0.01340953, -0.06294606,
        0.06100728, -0.01510512,  0.05462663,  0.02608098, -0.02559752,
        0.05680516, -0.01966719, -0.04399163, -0.030495  , -0.0308644 ,
        0.02145895,  0.03642636, -0.04693146, -0.05628132, -0.02680688,
        0.00846783,  0.0445124 ,  0.01025795,  0.01845859,  0.03335163,
       -0.01537714,  0.03230735,  0.06163692,  0.00010507,  0.04527271,
        0.04950059,  0.01912753,  0.04179293,  0.05514144, -0.05853245,
        0.00903072, -0.03254493, -0.00631456,  0.00458713, -0.00897077,
        0.02222857,  0.00341678,  0.06897668, -0.01211502,  0.10197832,
       -0.05306243, -0.03212267,  0.03164901,  0.02576393,  0.0135391 ,
       -0.03992961, -0.0109202 , -0.00201071,  0.00757445, -0.06248039,
       -0.00257573,  0.03622422, -0.00919204,  0.04767835, -0.04604388,
       -0.03426005,  0.04008616,  0.01734728, -0.01375834,  0.01505349,
        0.04367326,  0.04850455,  0.01016187,  0.02804698,  0.02704554,
       -0.06344569, -0.00677349,  0.05364538, -0.04205398,  0.04576857,
       -0.01472281, -0.00222749,  0.04770736, -0.03630973, -0.06677592,
       -0.01413644, -0.05848285, -0.03845937,  0.04353745, -0.04596702,
       -0.0577588 ,  0.02057918, -0.07081554, -0.00312039, -0.04776334,
        0.0061854 ,  0.02170933, -0.04816211,  0.04098115, -0.01409933,
       -0.03906237, -0.03261985,  0.07526575,  0.02189938, -0.06676587,
       -0.03801889, -0.04672712,  0.05484797,  0.02623602,  0.05705193,
        0.05310635,  0.0118135 , -0.05779904, -0.06031591,  0.11297597,
        0.05530044,  0.05309427,  0.0847534 , -0.03714605,  0.00408372,
       -0.02554936,  0.05561572,  0.01739844, -0.01456344,  0.00546556,
       -0.0695719 , -0.01023324, -0.04728689, -0.0670394 ,  0.02145054,
        0.06443892,  0.01297831, -0.02528835,  0.01280197,  0.01568981,
        0.01847136, -0.00213325, -0.03277086, -0.03302687,  0.00492474,
       -0.05498023,  0.04756507, -0.04747815,  0.10772855, -0.07756478,
        0.03970002,  0.05918756, -0.05535463,  0.00074084, -0.00536965,
       -0.05806309, -0.00531726, -0.04292773,  0.06787517,  0.01506379,
       -0.02266072, -0.00625078, -0.06015545,  0.02166701,  0.03745877,
       -0.10010569, -0.06584737, -0.03949844,  0.09683568, -0.00029282,
        0.00131516, -0.01271166,  0.03039811, -0.03469797, -0.01298763,
       -0.01335639,  0.02002659,  0.04848332,  0.02280388,  0.00489054,
        0.02691584, -0.04177703,  0.04938192,  0.0168847 , -0.04873618,
        0.02158107,  0.00170273, -0.01297865,  0.00122843,  0.00843124,
       -0.02903359,  0.06780674,  0.01894188, -0.00497952,  0.02406156,
       -0.00692734,  0.0480898 , -0.00500773, -0.0216024 ,  0.03775008,
        0.05133073,  0.04601539,  0.02782964,  0.05762751, -0.05733642,
        0.05221717, -0.03261093, -0.05045099,  0.01994987,  0.02962154,
        0.04925085, -0.07737774, -0.05657306, -0.03208533,  0.03856513,
       -0.03272866, -0.06603148, -0.00348924, -0.06541417, -0.01703358,
        0.04905311, -0.02437359, -0.06361713, -0.06160083,  0.02613706,
       -0.04626381,  0.03303308,  0.03376429, -0.05002112,  0.0112716 ,
       -0.03276235,  0.01381517,  0.05872491, -0.05950417, -0.0658569 ,
       -0.00512219, -0.02565468,  0.01775126,  0.01939261, -0.03974044,
        0.05520787,  0.0171796 , -0.06828529, -0.00088945, -0.04330327,
       -0.04207797,  0.05826313, -0.01688557,  0.06000157,  0.01710823,
        0.0214674 ,  0.00906935,  0.0549342 ,  0.04150207, -0.01222202,
        0.02499335,  0.00097738, -0.05122247,  0.02019784, -0.06417643,
        0.07330912,  0.02895209, -0.00012827, -0.04994339,  0.00848978,
        0.05805404,  0.06091613, -0.02075062, -0.0038926 , -0.01466825,
        0.04652022, -0.00042007,  0.06424164, -0.01529172,  0.04212146,
        0.04466938, -0.03911505, -0.02939729, -0.02483137,  0.04056912,
        0.02736827,  0.00914595,  0.06146059, -0.06736621, -0.05116177,
       -0.06752091, -0.03742753, -0.0296349 , -0.03702378,  0.04592508,
       -0.04846114,  0.10422388, -0.06133935, -0.03763162,  0.01273714,
       -0.0256919 ,  0.02615782,  0.00362816, -0.04967657, -0.02952319,
        0.02516334,  0.03035173,  0.01083948,  0.04183457, -0.04402133,
       -0.04517752, -0.04750552,  0.00406832, -0.06431906,  0.02182986,
        0.05140937, -0.00488047,  0.0174079 , -0.00229904, -0.04867466,
       -0.0585434 ,  0.00952654,  0.0340989 ,  0.04663004, -0.02384141,
        0.04481387, -0.04853568,  0.00913449,  0.00613086,  0.01651601,
       -0.0780843 ,  0.04877641, -0.04041425, -0.02577748, -0.06024192,
        0.03661654,  0.00998877, -0.02194038, -0.00046279, -0.00919664,
        0.04877417, -0.02106004,  0.05454858, -0.05068926, -0.01604749,
       -0.04650255,  0.05201323, -0.05760678,  0.04448525,  0.04287169,
        0.06029905,  0.06388846,  0.01340887, -0.06783635,  0.06091038,
       -0.04835383, -0.07253283,  0.0539487 , -0.08964941,  0.02301412,
       -0.00706921, -0.00647406, -0.05862577,  0.05437503, -0.01029982,
       -0.05593654,  0.05901633, -0.06720234, -0.02751224,  0.0285051 ,
       -0.01434351, -0.02031715,  0.0245509 , -0.00719581,  0.0498337 ,
       -0.0592702 ,  0.05968297,  0.01694378, -0.05895277,  0.06436513,
        0.01480134, -0.03944893, -0.05655546, -0.04078228,  0.03918803,
        0.00873325,  0.02636947, -0.06233535, -0.00706722, -0.02484037,
       -0.00830441, -0.0142424 ,  0.03507293, -0.01321688, -0.07174658,
        0.01636514, -0.00769878,  0.02974752,  0.04273086, -0.01993361,
        0.02861152,  0.04197089, -0.01507609,  0.01447403, -0.05115371,
        0.01885322, -0.01085396, -0.11166637,  0.05743435,  0.01920477,
       -0.05404697, -0.04272072, -0.01433513, -0.00836455, -0.00382889,
        0.02870366,  0.06746998, -0.04809454,  0.00097041,  0.06454285,
        0.01592386,  0.01909108,  0.04667838,  0.01523895, -0.00287385,
        0.05495049,  0.03311313,  0.03825879,  0.06312161, -0.00838411,
        0.04415325,  0.05842169,  0.04645902,  0.08257765, -0.01262631,
        0.04877787,  0.00575482, -0.02158699,  0.05249387,  0.01047641,
       -0.01741789, -0.00698602, -0.03328903,  0.01894333, -0.01029229,
       -0.04723966,  0.05022682, -0.0480519 , -0.06078862,  0.08220727,
       -0.00819226, -0.01274004,  0.01406324, -0.00151813, -0.00398977,
       -0.02208438, -0.0480222 , -0.05503081, -0.04412683,  0.04026026,
       -0.04580159,  0.04789461, -0.04386308, -0.01020516,  0.02627327,
        0.01802862, -0.08573422,  0.01360963, -0.04410618, -0.06312696,
        0.03486938, -0.05614203,  0.03417183, -0.05826972,  0.0519412 ,
       -0.040929  ,  0.05019714,  0.01388979, -0.05817528, -0.03194496,
       -0.03685883, -0.05003782,  0.06158189,  0.03323727, -0.00398209,
        0.01708449,  0.03782252,  0.05671677,  0.00831079,  0.02728437,
       -0.00722008, -0.00417433,  0.05007619,  0.01160676, -0.00934848,
       -0.06332258,  0.01774024, -0.0145871 , -0.05774269,  0.06348779,
        0.03692398, -0.02630005,  0.03665813, -0.01223178,  0.01555196,
        0.04886926, -0.05950654,  0.01159101, -0.03156234, -0.01505837,
       -0.02906902,  0.06403178,  0.04890949, -0.05415046,  0.06553847,
        0.04468614,  0.00919456, -0.00247315,  0.01045631,  0.05730727,
        0.06942752, -0.03359847,  0.04912696, -0.04469884,  0.00075902,
       -0.02260221,  0.03450099, -0.00624029, -0.00477524, -0.02140925,
       -0.04628824,  0.04441322,  0.05006309,  0.04719676,  0.02325969,
        0.03400015,  0.05525723,  0.00497319, -0.07475576, -0.02778674,
       -0.03361143, -0.01950759,  0.06525443, -0.02678801,  0.04728568,
        0.02917658, -0.02080669,  0.03867505, -0.02267782,  0.00848212,
        0.03622892, -0.00859405, -0.03525306,  0.01428093, -0.0745097 ,
       -0.03309461, -0.07022033,  0.03603973,  0.03144769, -0.01726364,
        0.02310057, -0.02301078,  0.06352917, -0.04904172, -0.01435572,
       -0.06702514,  0.00713479,  0.03224616,  0.02836283,  0.02494003,
        0.05459946,  0.0594446 ,  0.01795571,  0.04966679,  0.01439686,
       -0.04161709, -0.02521713, -0.03105078, -0.05868803, -0.0521078 ,
       -0.04566897,  0.02949326, -0.0227761 , -0.05888623,  0.04132635,
       -0.05826614,  0.0480237 ,  0.03466976, -0.06262673,  0.06401269,
        0.0253212 , -0.05420306,  0.03212521,  0.0033784 , -0.04969216,
       -0.05045897,  0.03113154,  0.03683804,  0.06330634,  0.0376904 ,
        0.06757024, -0.02777942,  0.09041066, -0.04429911, -0.01677389,
       -0.02320677,  0.00092426,  0.0522385 , -0.0147125 , -0.0316902 ,
        0.00517368, -0.0391661 ,  0.0904642 , -0.04840381,  0.01798324,
       -0.05356038, -0.0717759 , -0.07733724,  0.02162017, -0.00516033,
        0.0363056 ,  0.05287293,  0.03840883,  0.03802092, -0.00243192,
       -0.03084692, -0.0575586 , -0.0236513 ,  0.02130401,  0.04689748,
       -0.01836536, -0.06242229,  0.04251221,  0.06579036,  0.05843649,
       -0.00154234,  0.03966697,  0.05496246, -0.02159047, -0.00563004,
        0.04265502,  0.03533547, -0.00956506, -0.00219043,  0.04914487,
        0.02895665, -0.03714206,  0.03347052, -0.05927857,  0.00665819,
       -0.04721805, -0.07563639,  0.04893867,  0.00790088,  0.06069352,
        0.06589334,  0.02386768, -0.00320283,  0.03960491,  0.0419613 ,
       -0.01892208, -0.04881731, -0.05307779,  0.02225012, -0.05072653,
       -0.04128261, -0.01824052, -0.01224875,  0.03474744,  0.00720443,
       -0.02841852, -0.01942328,  0.0031965 ,  0.06544683,  0.02722446,
       -0.06518205, -0.01472067,  0.01347743, -0.03770592, -0.04336114,
        0.02236951,  0.04974928,  0.03562613, -0.03985786,  0.05452666,
       -0.02134745,  0.02781245,  0.04807139,  0.00853444, -0.06945569,
       -0.04961846,  0.01116744, -0.00981702, -0.02712346, -0.00851909,
        0.03424413,  0.00646405, -0.05724387, -0.00043597, -0.02225278,
        0.05648588, -0.04040722,  0.0072362 ,  0.06709953,  0.05305498,
        0.017071  ,  0.06599609,  0.02198709,  0.04310399, -0.05507261,
       -0.04290765,  0.0277337 , -0.0505163 , -0.0649536 ,  0.03151101,
       -0.01238905,  0.07466003,  0.04209925,  0.02857335, -0.05065861,
        0.03732137, -0.01713676, -0.05820834,  0.01953886, -0.06259465,
       -0.05908129,  0.01364181,  0.07825941, -0.0491681 ,  0.10131758,
       -0.07821093, -0.0472321 ,  0.02455053, -0.03868328,  0.01675637,
        0.06046061, -0.00191497, -0.04322908,  0.02020105,  0.05314559,
       -0.00704901,  0.00099193,  0.03821871, -0.00315432,  0.04179208,
        0.04689806, -0.0086365 , -0.03472315,  0.04959911, -0.04699428,
       -0.03990216,  0.06187751,  0.03274471,  0.04802721,  0.03470156,
       -0.04976156,  0.05397421, -0.02411817, -0.0561352 , -0.01529458,
       -0.00347958, -0.05517508,  0.00805432,  0.02292649, -0.04505236,
       -0.03715898, -0.01502724,  0.01379696, -0.01797008,  0.04287562,
       -0.06746414, -0.03666969, -0.04250623,  0.02364587, -0.03389731,
       -0.05794711, -0.05205134,  0.06144318,  0.05332677, -0.03001215,
        0.03628244, -0.02997526, -0.04726359, -0.06400843,  0.0305719 ,
        0.05800711, -0.05764245,  0.0055555 , -0.0103391 , -0.04759252,
       -0.04503962,  0.03169075, -0.08148788,  0.06789927,  0.03174809,
        0.00384139,  0.04991922,  0.04136202,  0.02118946, -0.04046963,
        0.00895532, -0.02939275, -0.05306218, -0.03441501, -0.03991329,
        0.02521899,  0.06074818,  0.0612024 ,  0.06039105, -0.00579105,
       -0.00257046, -0.0211879 ,  0.01884517,  0.00953596, -0.04677365,
       -0.00504393, -0.0422954 ,  0.02071201, -0.05968835, -0.00100327,
       -0.04933946, -0.04184846, -0.06499656,  0.03510487, -0.02144185,
       -0.03129695,  0.0104201 ,  0.00411873,  0.01703625, -0.04075227,
       -0.02700629, -0.02282299,  0.03060033,  0.00151751,  0.06509829,
       -0.03826668,  0.04936533,  0.05228626,  0.02911021,  0.05853009,
        0.05900225, -0.02024092, -0.05078531, -0.06765159, -0.01475852,
       -0.01850148, -0.03923226, -0.00606541,  0.05838662, -0.00248045,
        0.01566372,  0.00163237,  0.02051106,  0.03790848, -0.05235885,
       -0.03207511, -0.01351603,  0.07184897, -0.04468418, -0.01443752,
        0.01421285, -0.03143227, -0.00821584, -0.05553431, -0.03527627,
        0.00687965,  0.00915645, -0.00857254,  0.04111375,  0.00688421,
       -0.01805411,  0.05926739,  0.024111  , -0.01877209,  0.06239301,
       -0.05872532, -0.00247674,  0.05379154,  0.00356066, -0.04425195,
        0.03866294, -0.06701747, -0.05498832, -0.04369364,  0.07102133,
        0.00250937, -0.00275382,  0.03006196,  0.0399949 , -0.04169014,
        0.03702056, -0.06206661,  0.01115416, -0.05851743, -0.01950399,
        0.01901136,  0.00096517, -0.05988241, -0.06003897, -0.01252597,
        0.06250738, -0.02598946,  0.03306301, -0.0532368 ,  0.06366771,
        0.04705013,  0.02857811,  0.02408861,  0.00511974, -0.06581322,
        0.01355143, -0.04028335, -0.06236709,  0.06695849, -0.05353275,
        0.01639166, -0.0645048 , -0.05037842,  0.00909738,  0.05118217,
       -0.04718736, -0.01611917, -0.05082874,  0.00634879,  0.06518917,
        0.08104189, -0.09954074, -0.04943076,  0.05920038,  0.05430028,
       -0.02331848,  0.01786461,  0.042836  ,  0.03728686,  0.03376361,
        0.06379782,  0.03417662,  0.02578485,  0.03645884,  0.00924096,
        0.0338061 , -0.02806808, -0.04962701,  0.02341893, -0.05520385,
        0.01760828, -0.05558517,  0.06967801,  0.04458525, -0.03743316,
        0.01450988, -0.02337051, -0.02006529,  0.05220459,  0.04887258,
       -0.0136549 ,  0.06711223, -0.05353866, -0.02538758, -0.01963754,
       -0.00180357,  0.02390978,  0.03368624, -0.03475981,  0.02709343,
       -0.02765062,  0.03945585, -0.03023228,  0.02398378,  0.06107442,
       -0.05513151, -0.05139918,  0.00833456, -0.00851802, -0.01213076,
        0.01894868,  0.06827832, -0.03613872, -0.05923394,  0.03267112,
       -0.01566664, -0.01907218, -0.02910691, -0.04383189, -0.02966722,
        0.06373216, -0.08342219, -0.01572192,  0.02541998, -0.06335298,
       -0.04599231, -0.02637636, -0.06759251,  0.04157218,  0.03645134,
        0.06168087,  0.03481379, -0.07687014,  0.06372779,  0.00623477,
        0.0452509 ,  0.09681483, -0.17673168,  0.0684211 ,  0.046364  ,
       -0.05755769,  0.00291638,  0.00959636,  0.02316988,  0.00937487,
       -0.01096919,  0.06814543, -0.04539631,  0.01624575, -0.06809995,
       -0.02061831, -0.01076579, -0.03295235, -0.00982305, -0.02860021,
       -0.02647625, -0.03136773, -0.01886466, -0.05003516,  0.04634511,
        0.05250504,  0.04689164, -0.00891127,  0.04553944, -0.05417959,
       -0.03851239, -0.01191101, -0.0315445 ,  0.06666432,  0.04542756,
       -0.01501602,  0.06446003,  0.06171936,  0.06463858,  0.04459265,
        0.00385769,  0.06090331, -0.00226514,  0.00408913,  0.05837375,
       -0.08706222,  0.03879588,  0.00258265, -0.02534889, -0.03581751,
       -0.07742504, -0.00969264, -0.0299996 , -0.00863138, -0.06178039,
        0.01146267,  0.00971513, -0.03500876,  0.05973203,  0.05704117,
       -0.03424954,  0.05676161, -0.00188485,  0.06647483,  0.0063884 ,
        0.00789099, -0.00539555,  0.04094536, -0.04561901, -0.01452686,
        0.0324164 ,  0.00772642, -0.07437003, -0.01570263,  0.02705326,
        0.02825502,  0.06144076, -0.06281831,  0.0303932 , -0.04237553,
        0.00226256,  0.03648954, -0.02152959,  0.01277964, -0.00369124,
       -0.0613079 ,  0.0107591 ,  0.03263848,  0.06375041,  0.06943618,
       -0.09896708, -0.05261325,  0.04268349,  0.04571991,  0.02695897,
       -0.0334987 ,  0.04058429, -0.01383945, -0.0289737 ,  0.0126008 ,
       -0.04456419, -0.03711697,  0.05616874,  0.032376  , -0.00557523,
       -0.05086645, -0.00108689, -0.01898989, -0.0071689 ,  0.01783865,
       -0.07244593,  0.03644762,  0.04739393, -0.01545432, -0.03110168,
       -0.02073837, -0.06732979,  0.02705065,  0.03288118,  0.02032736,
        0.05136994, -0.02342501,  0.02111443,  0.03089964,  0.02049594,
        0.04570455, -0.02509744,  0.00777681,  0.06764808,  0.0425099 ,
       -0.0236089 ,  0.0669447 , -0.02094458,  0.00526043, -0.04864538,
        0.05344872,  0.02890046, -0.04241132,  0.03276403, -0.10305309,
        0.07549956, -0.06077792, -0.02774839, -0.06102667, -0.05882598,
        0.04780531, -0.02690593,  0.01299507, -0.03135295,  0.07297917,
       -0.01246751,  0.00492284, -0.03738299,  0.05078462,  0.00739436
};

FCLayer::FCLayer (){
	//bias = new double[1];
	//input_size = 0;
	//output_size = 0;
}

FCLayer::FCLayer (int input_sz, int output_sz, 
					double scale, int zero_point,
					int batch, bool default_weight) {
	input_size = input_sz;
	output_size = output_sz;
	batch_size = batch;
	quant_zero_point = zero_point;
	quant_scale = scale;

	cout << "set input size to: " << input_size << "\n";
	cout << "set output size to: " << output_size << "\n";

	bias = new double[output_size];
	for(int j = 0; j < output_size; j++) {
		if(default_weight){
			bias[j] = initial_model_bias[j];
		}
		else{
			bias[j] = (double)rand()/(RAND_MAX);
		}
	}

	weights = new double*[input_size];
	for(int i = 0; i < input_size; i++) {
		weights[i] = new double[output_size];
		for(int j = 0; j < output_size; j++){
	    	if(default_weight){
	    		//initial_model_weights was 256x2 but now flattened
	    		//input_size = 256, output_size = 2
	    		weights[i][j] = initial_model_weights[j+i*output_size];
	    	}else{
	    		if(rand()%2 == 0){
	    			weights[i][j] = -1*(double)rand()/(RAND_MAX);
	    		}else{
	    			weights[i][j] = (double)rand()/(RAND_MAX);
	    		}
	    	}
			
	    }
	}

	output_error_softmax = new double*[batch_size];
	for(int b = 0; b < batch_size; b++) {
	    output_error_softmax[b] = new double[output_size];
	}
}


void FCLayer::set_weights_bias(double **new_weights, double *new_bias){
	// Set weights
	for(int i = 0; i < input_size; ++i) {
		for (int j = 0; j < output_size; ++j){
			weights[i][j] = new_weights[i][j];
		}		
	}

	// Set bias
	for(int j = 0; j < output_size; j++) {
		bias[j] = new_bias[j];
	}
}

void softmax(double *input_output_data, int classes){
	double sum = 0;
	double max = -10000.0;
	for(int j = 0; j < classes; j++){
		if(input_output_data[j] > max){
			max = input_output_data[j];
		}
	}
	for(int j = 0; j < classes; j++){
		input_output_data[j] = exp(input_output_data[j]-max);
		sum += input_output_data[j];
	}
	for(int j = 0; j < classes; j++){
		input_output_data[j] = input_output_data[j]/sum;
	}
}

void softmax_prime(double *pred, double *result, int classes){
	for(int a = 0; a < classes; a++){
		result[a] = 0;
		for(int b = 0; b < classes; b++){
			if(a == b){
				result[a] += pred[a]*(1-pred[a]);
			}else{
				result[a] += -1*pred[a]*pred[b];
			}
		}
	}
}

void FCLayer::dequantize(int *input_data, double *input_float){
	//use double input [input_size]; when calling
	//input = (input - zero_point) * scale
	for(int i = 0; i < input_size; i++){
		input_float[i] = (input_data[i]-quant_zero_point)*quant_scale;
	}
}


void FCLayer::forward (double **input_float, double **output) {
	/*
	https://towardsdatascience.com/math-neural-network-from-scratch-in-python-d6da9f29ce65
	*/

	//self.output = np.dot(self.input, self.weights) + self.bias
	for(int b = 0; b < batch_size; b++){
		for(int j = 0; j < output_size; j++){
			output[b][j] = 0.0;
			for(int i = 0; i < input_size; i++){
				output[b][j] += input_float[b][i]*weights[i][j];
			}
			output[b][j] += bias[j];
		}
		//softmax to get probabilities
		softmax(output[b], output_size);
	}
}

double L2(double **weight, int input_size, int output_size, int batch_size){
	double sum = 0.0;
	for(int i = 0; i < input_size; i++){
		for(int j = 0; j < output_size; j++){
			sum += pow(weight[i][j],2);
		}
	}
	return sum / batch_size;
}

void cross_entropy_prime(double *pred, int *real, double *result, int classes){
	for(int j = 0; j < classes; j++){
		result[j] = -1.0*real[j]/pred[j];
	}
}

double cross_entropy_loss(double **pred, int **real, int batch_size, int classes){
	double result = 0.0;
	double epsilon = 0.0000001;

	for(int b = 0; b < batch_size; b++){
		for(int j = 0; j < classes; j++){
			if(real[b][j] == 1 and pred[b][j] < epsilon){
				result -= real[b][j]*log(epsilon);
			}else{
				result -= real[b][j]*log(pred[b][j]);
			}
		}
	}
	return result/(batch_size);
}

void mse_prime(double *pred, int *real, double *result, int classes){
	for(int i = 0; i < classes; i++){
		result[i] += 2*(pred[i]-real[i]);
	}

}

double mse(double **pred, int **real, int batch_size, int classes){
	double result = 0.0;

	for(int b = 0; b < batch_size; b++){
		for(int j = 0; j < classes; j++){
			result += pow((pred[b][j]-real[b][j]), 2);
		}
	}
	return result/(classes*batch_size);
}

void combined_ce_softmax_prime(double *pred, int *real, double *result, int classes){
	for(int i = 0; i < classes; i++){
		result[i] = pred[i] - real[i];
		//cout << result[i] << "\n";
		assert(result[i] >= -1 && result[i] <= 1);
	}
}

double accuracy(double **pred, int **real, int batch_size, int classes){
	double correct = 0.0;

	for(int b = 0; b < batch_size; b++){
		for(int j = 0; j < classes; j++){
			if((pred[b][j] >= 0.5 && real[b][j] == 1)||(pred[b][j] < 0.5 && real[b][j] == 0)){
				correct += 1;
			}
		}
	}
	return correct/(classes*batch_size);
}

void FCLayer::backward (double **output, int **ground_truth, 
						double **input_error, double **input_float,
						double learning_rate, double lambda) {

	//double **output_error = new double*[batch_size];

	for(int b = 0; b < batch_size; b++) {
	    //output_error[b] = new double[output_size];
	    //cross_entropy_prime(output[b], ground_truth[b], output_error[b], output_size);
	    //softmax_prime(output_error[b], output_error_softmax[b], output_size);
	    combined_ce_softmax_prime(output[b], ground_truth[b], output_error_softmax[b], output_size);
	}

	for(int b = 0; b < batch_size; b++){
		//input_error = np.dot(output_error, self.weights.T)
		// batch_sizexinput_size = batch_sizexoutput_size dot output_sizexinput_size
	    for(int i = 0; i < input_size; i++) {
	    	input_error[b][i] = 0.0;
		    for(int j = 0; j < output_size; j++){
				input_error[b][i] += output_error_softmax[b][j]*weights[i][j]/batch_size;
		    }
		}
	}

	//weights_error = np.dot(self.input.T, output_error)
	double weights_error[input_size][output_size];

	for(int i = 0; i < input_size; i++) {
		for(int j = 0; j < output_size; j++){
			weights_error[i][j] = 0.0;
		}
	}

	for(int i = 0; i < input_size; i++) {
		// input_sizexoutput_size = input_sizexbatch_size dot batch_sizexoutput_size
		for(int j = 0; j < output_size; j++){
			for(int b = 0; b < batch_size; b++){
				weights_error[i][j] += input_float[b][i]*output_error_softmax[b][j]/batch_size;
		    }
		}
	}

	//self.weights -= learning_rate * weights_error
	for(int i = 0; i < input_size; ++i) {
		for(int j = 0; j < output_size; j++){
			this->weights[i][j] = this->weights[i][j]*(1-learning_rate*lambda/batch_size)-learning_rate*weights_error[i][j];
		}
	}
	
	//self.bias -= learning_rate * output_error
	for(int j = 0; j < output_size; j++){
		for(int b = 0; b < batch_size; b++) {
			this->bias[j] -= learning_rate*output_error_softmax[b][j]/batch_size;
		}
	}
}

void FCLayer::cleanup(){
	cout << "cleaning up object\n";
	for(int i = 0; i < input_size; i++) {
		delete [] weights[i];
	}
	for(int b = 0; b < batch_size; b++){
	    delete [] output_error_softmax[b];
	}
	delete [] output_error_softmax;
	delete[] weights;
	delete[] bias;
}

FCLayer::~FCLayer() { }

void predict(double **input_float, FCLayer *model, double **output, int batch_size, int classes){
	model->forward(input_float, output);

	for(int b = 0; b < batch_size; b++){
		for(int j = 0; j < classes; j++){
			if(output[b][j] >= 0.5){
				output[b][j] = 1.0;
			}else{
				output[b][j] = 0.0;
			}
		}
	}
}

void FL_round_simulation(double **input_f, int **input_i, int **ground_truth, int local_episodes, 
						double learning_rate, FCLayer *model, double lambda, 
						bool verbose, bool local, bool unquantize){
	if(verbose == true){
		if(local == true){
			cout << "\tstarted sim\n";
		}else{
			//Serial.print("\tstarted sim\n");
		}
	}
	double **output = new double*[model->batch_size];
	double **input_error = new double*[model->batch_size];
	double **input_float = new double*[model->batch_size];

	if(verbose == true){
		if(local == true){
			cout << "\tallocated\n";
		}else{
			//Serial.print("\tallocated\n");
		}
	}

	for(int b = 0; b < model->batch_size; b++) {
		output[b] = new double[model->output_size];
		for(int j = 0; j < model->output_size; j++){
			output[b][j] = 0.0;
		}

		input_error[b] = new double[model->input_size];
		for(int i = 0; i < model->input_size; i++){
			input_error[b][i] = 0.0;
		}
		if(unquantize == true){
			model->dequantize(input_i[b], input_float[b]);
		}else{
			input_float[b] = input_f[b];
		}
	}

	if(verbose == true){
		if(local == true){
			cout << "\tallocated part 2\n";
			cout << "\tinitial bias loaded " << model->bias[0] << " " << model->bias[1] << "\n";
			cout << "\tinitial output " << output[0][0] << " " << output[0][1] << "\n";
		}else{
			//Serial.print("\tallocated\n");
		}
	}

	for(int epi = 0; epi < local_episodes; epi++){
		if(verbose == true){
			if(local == true){
				cout << "EPISODE " << epi << "\n";
				cout << "\tforward\n";
				cout << "\t\tbias loaded " << model->bias[0] << " " << model->bias[1] << "\n";
			}else{
				//Serial.print("\tEPISODE");
        		//Serial.println(epi);
        		//Serial.print("\tforward\n\t\t bias loaded");
				//Serial.print(model->bias[0], model->bias[1]);
			}
		}
		//forward
		model->forward(input_float, output);

		if(verbose == true){
			if(local == true){
				cout << "\tsoftmax " << output[0][0] << " " << output[0][1] << "\n";
			}else{
				//Serial.print("\tsoftmax");
				//Serial.println(output[0][0]);
				//Serial.println(output[0][1]);
			}
		}

		//calculate and print error
		double l2_error = lambda*L2(model->weights, model->input_size, model->output_size, model->batch_size)/2;
		double error = cross_entropy_loss(output, ground_truth, model->batch_size, model->output_size)
						+l2_error;
		double acc = accuracy(output, ground_truth, model->batch_size, model->output_size);
		if(epi == local_episodes-1){
			cout << " train acc: " << acc;
		}
		//cout << "\tlocal episode : " << epi << " error: " << error << " accuracy: " << acc << "\n";

		//backward
		model->backward(output, ground_truth, input_error, input_float, learning_rate, lambda);

		if(verbose == true){
			if(local == true){
				cout << "\tbackward\n";
			}else{
				//Serial.print("\tbackward\n");
			}
		}
		//reset input_error and output in forward and backward 
	}

	if(verbose == true){
		if(local == true){
			cout << "\tdone loop\n";
		}else{
			//Serial.print("\tdone loop\n");
		}
	}

	for(int b = 0; b < model->batch_size; b++) {
		delete [] input_error[b];
		delete [] output[b];
		if(unquantize == true){
			delete [] input_float[b];
		}
	}
	delete [] input_error;
	delete [] output;
	delete [] input_float;

	if(verbose == true){
		if(local == true){
			cout << "\tdone de-allocation\n";
		}else{
			//Serial.print("\tdone de-allocation\n");
		}
	}
}